package com.cheng.testnetwork.util;

import android.util.Log;

import com.cheng.testnetwork.BuildConfig;

public final class LogUtil {

	/** 日志输出级别NONE */
	public static final int LEVEL_NONE = 0;

	/** 是否允许输出log
	 *  -1：  不允许
	 *  其他：根据等级允许
	 * */
	public static final int DEBUG_ABLE = BuildConfig.DEBUG ? 10 : LEVEL_NONE;

	/** 日志输出时的TAG */
	private static String mTag = "zhengbajing";

	/** 日志输出级别V */
	public static final int LEVEL_VERBOSE = Log.VERBOSE;

	/** 日志输出级别D */
	public static final int LEVEL_DEBUG = Log.DEBUG;

	/** 日志输出级别I */
	public static final int LEVEL_INFO = Log.INFO;

	/** 日志输出级别W */
	public static final int LEVEL_WARN = Log.WARN;

	/** 日志输出级别E */
	public static final int LEVEL_ERROR = Log.ERROR;

	/**
	 * 打印的方法名数量
	 */
	private static int methodCount = 4;

	private LogUtil() throws InstantiationException {
		throw new InstantiationException("This class is not created for instantiation");
	}

	/** 以级别为v 的形式输出LOG */

	public static void v(String msg) {

		if (DEBUG_ABLE >= LEVEL_VERBOSE) {

			Log.println(LEVEL_VERBOSE,mTag, methodMsg(LEVEL_VERBOSE)+msg);

		}

	}

	/** 以级别为 d 的形式输出LOG */

	public static void d(String msg) {

		if (DEBUG_ABLE >= LEVEL_DEBUG) {

			Log.println(LEVEL_DEBUG,mTag,methodMsg(LEVEL_DEBUG)+ msg);

		}

	}
	/** 以级别为 d 的形式输出LOG */
	public static void d(String tag, String msg) {

		if (DEBUG_ABLE >= LEVEL_DEBUG) {

			Log.println(LEVEL_DEBUG,tag,methodMsg(LEVEL_DEBUG)+ msg);

		}

	}

	/** 以级别为 i 的形式输出LOG */

	public static void i(String msg) {

		if (DEBUG_ABLE >= LEVEL_INFO) {

			Log.println(LEVEL_INFO,mTag,methodMsg(LEVEL_INFO)+ msg);

		}

	}

	/** 以级别为 w 的形式输出LOG */

	public static void w(String msg) {

		if (DEBUG_ABLE >= LEVEL_WARN) {

			Log.println(LEVEL_WARN,mTag,methodMsg(LEVEL_WARN)+ msg);

		}

	}

	/** 以级别为 w 的形式输出Throwable */

	public static void w(Throwable tr) {

		if (DEBUG_ABLE >= LEVEL_WARN) {

			Log.w(mTag, methodMsg(LEVEL_WARN), tr);

		}

	}

	/** 以级别为 w 的形式输出LOG信息和Throwable */

	public static void w(String msg, Throwable tr) {

		if (DEBUG_ABLE >= LEVEL_WARN && null != msg) {

			Log.w(mTag, methodMsg(LEVEL_WARN)+msg, tr);

		}

	}

	/** 以级别为 e 的形式输出LOG */

	public static void e(String msg) {

		if (DEBUG_ABLE >= LEVEL_ERROR) {

			Log.println(LEVEL_ERROR,mTag,methodMsg(LEVEL_ERROR)+ msg);

		}

	}

	/** 以级别为 e 的形式输出Throwable */

	public static void e(Throwable tr) {

		if (DEBUG_ABLE >= LEVEL_ERROR) {

			Log.e(mTag, methodMsg(LEVEL_ERROR)+"", tr);

		}

	}

	/** 以级别为 e 的形式输出LOG信息和Throwable */

	public static void e(String msg, Throwable tr) {

		if (DEBUG_ABLE >= LEVEL_ERROR && null != msg) {

			Log.e(mTag, methodMsg(LEVEL_ERROR)+msg, tr);

		}

	}

	/**
	 * 方法名 类名  线程名 等信息
	 * @return
	 */
	private static String methodMsg(int priority) {

		StackTraceElement[] trace = Thread.currentThread().getStackTrace();

		StringBuilder builder = new StringBuilder();
		builder.append(" Thread: " + Thread.currentThread().getName());

		String level = "";

		int stackOffset = getStackOffset(trace) + 0;

		//corresponding method count with the current stack may exceeds the stack trace. Trims the count
		if (methodCount + stackOffset > trace.length) {
			methodCount = trace.length - stackOffset - 1;
		}

		for (int i = methodCount; i > 0; i--) {
			int stackIndex = i + stackOffset;
			if (stackIndex >= trace.length) {
				continue;
			}
			builder.append(" | ")
					.append(' ')
					.append(level)
					.append(getSimpleClassName(trace[stackIndex].getClassName()))
					.append(".")
					.append(trace[stackIndex].getMethodName())
					.append(" ")
					.append(" (")
					.append(trace[stackIndex].getFileName())
					.append(":")
					.append(trace[stackIndex].getLineNumber())
					.append(")");
			level += " ";

//			Log.println(LEVEL_INFO,mTag,builder.toString());
//			d(trace[stackIndex].getLineNumber()+"");
		}
		int stackIndex = 1 + stackOffset;
		Log.println(priority,mTag,"("+trace[stackIndex].getFileName() +":"+  trace[stackIndex].getLineNumber()+")");
		return builder.toString() + "\n";
	}

	private static String getSimpleClassName(String name) {
		int lastIndex = name.lastIndexOf(".");
		return name.substring(lastIndex + 1);
	}

	/**
	 * 方法名 类名  线程名 等信息
	 * @return
	 */
//	private static String methodMsg() {
//		StackTraceElement[] trace = Thread.currentThread().getStackTrace();
//		StringBuilder builder = new StringBuilder();
//		String className = trace[4].getClassName();
//
//		className = className.substring(className.lastIndexOf(".") + 1);
//		builder.append(" ClassName : ").append(className).append(" ║ ");
//		builder.append(" Thread: ").append(Thread.currentThread().getName());
//
//		int stackOffset = getStackOffset(trace);
//
//		//corresponding method count with the current stack may exceeds the stack trace. Trims the count
//		if (methodCount + stackOffset > trace.length) {
//			methodCount = trace.length - stackOffset - 1;
//		}
//
//		for (int i = methodCount; i > 0; i--) {
//			int stackIndex = i + stackOffset;
//			if (stackIndex >= trace.length) {
//				continue;
//			}
//
//			builder.append(" ║ ")
//					.append(trace[stackIndex].getMethodName())
//					.append(" ")
//					.append(" (")
//					.append(trace[stackIndex].getFileName())
//					.append(":")
//					.append(trace[stackIndex].getLineNumber())
//					.append(")");
//		}
//		return builder.toString() + "\n";
//	}

	private static int getStackOffset(StackTraceElement[] trace) {
		for (int i = 3; i < trace.length; i++) {
			StackTraceElement e = trace[i];
			String name = e.getClassName();
			if (!name.equals(LogUtil.class.getName()) && !name.equals(Log.class.getName())) {
				return --i;
			}
		}
		return -1;
	}

}
